_package("alz.gesture");

_import("alz.gesture.Gesture");

/**
 * 敲击手势
 */
_class("Tap", Gesture, function(){
	this.handles = ["tapstart", "tapcancel", "tap", "doubletap", "taphold", "singletap"];
	this.cancelThreshold = 10;
	this.doubleTapThreshold = 800;
	this.singleTapThreshold = 400;
	this.holdThreshold = 1000;
	this.fireClickEvent = false;
	this._init = function(config){
		_super._init.apply(this, arguments);
		this.timeout = 0;
		//this.startX
		//this.startY
	};
	this.onTouchStart = function(ev, touch){
		this.startX = touch.pageX;
		this.startY = touch.pageY;
		this.fire("tapstart", ev, this.getInfo(touch));
		if(this.listeners.taphold){
			this.timeout = runtime.startTimer(this.holdThreshold, this, function(){
				runtime.stopTimer(this.timeout);
				this.fire("taphold", ev, this.getInfo(touch));
			});
		}
		this.lastTouch = touch;
	},
	this.onTouchMove = function(ev, touch){
		if(this.isCancel(touch)){
			this.fire("tapcancel", ev, this.getInfo(touch));
			runtime.stopTimer(this.timeout);
			this.stop();
		}
		this.lastTouch = touch;
	};
	this.onTouchEnd = function(ev){
		var info = this.getInfo(this.lastTouch);
		this.fireTapEvent(ev, info);
		if(this.lastTapTime && ev.timeStamp - this.lastTapTime <= this.doubleTapThreshold){
			this.lastTapTime = null;
			ev.preventDefault();
			this.fire("doubletap", ev, info);
		}else{
			this.lastTapTime = ev.timeStamp;
		}
		if(this.listeners && this.listeners.singletap && this.singleTapThreshold && !this.preventSingleTap){
			this.fire("singletap", ev, info);
			this.preventSingleTap = true;
			runtime.startTimer(this.singleTapThreshold, this, function(){
				this.preventSingleTap = false;
			});
		}
		runtime.stopTimer(this.timeout);
	};
	this.fireTapEvent = function(ev, info){
		this.fire("tap", ev, info);
		if(ev.event){
			ev = ev.event;
		}
		var target = (ev.changedTouches ? ev.changedTouches[0] : ev).target;
		if(!target.disabled && this.fireClickEvent){
			var clickEvent = document.createEvent("MouseEvent");
			clickEvent.initMouseEvent("click", ev.bubbles, ev.cancelable, document.defaultView, ev.detail, ev.screenX, ev.screenY, ev.clientX,
				ev.clientY, ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey, ev.metaKey, ev.button, ev.relatedTarget);
			clickEvent.isSimulated = true;
			target.dispatchEvent(clickEvent);
		}
	};
	this.getInfo = function(touch){
		return {
			"pageX": touch.pageX,
			"pageY": touch.pageY
		};
	};
	this.isCancel = function(touch){
		return (
			Math.abs(touch.pageX - this.startX) >= this.cancelThreshold ||
			Math.abs(touch.pageY - this.startY) >= this.cancelThreshold
		);
	};
});